/*
 * @Author: Shane
 * @Date: 2022-05-31 22:48:35
 * @LastEditTime: 2022-12-13 20:22:53
 * @LastEditors: Shane
 * @Description: 
 * @FilePath: /kkhttp/lib/supmea_http_client.dart
 */

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:kk_http/kk_http_cfg.dart';
import 'package:kk_http/kk_http_method.dart';
import 'package:kk_http/kk_inner_dio.dart';

class KKHttpClient {
  late final KKInnerDio _dio;
  KKInnerDio get dio => _dio;

  KKHttpClient({
    BaseOptions? options,
    KKHttpCfg? cfg,
    List<Interceptor>? interceptors,
  }) : _dio = KKInnerDio(
          options: options,
          cfg: cfg,
          interceptors: interceptors,
        );

  final String _supmeaCancleKey = '_SUPMEA_KEY_LIFE_';

  /// 所有请求
  final Map<String, CancelToken> _requests = {};

  void updateBaseUrl(String url) {
    _dio.options.baseUrl = url;
  }

  ///
  Future<Response<T>> get<T>(
    String uri, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    dynamic key,
    KKProgressCallback? onReceiveProgress,
  }) async {
    Response<T> response = await request(
      HttpMethod.get,
      uri,
      queryParameters: queryParameters,
      key: key,
      options: options,
      onReceiveProgress: onReceiveProgress,
    );
    return response;
  }

  ///
  Future<Response<T>> post<T>(
    String uri, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    dynamic key,
    KKProgressCallback? onSendProgress,
    KKProgressCallback? onReceiveProgress,
  }) async {
    Response<T> response = await request(
      HttpMethod.post,
      uri,
      data: data,
      queryParameters: queryParameters,
      key: key,
      options: options,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    );
    return response;
  }

  Future<Response<T>> put<T>(
    String uri, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    dynamic key,
    KKProgressCallback? onSendProgress,
    KKProgressCallback? onReceiveProgress,
  }) async {
    Response<T> response = await request(
      HttpMethod.put,
      uri,
      data: data,
      queryParameters: queryParameters,
      key: key,
      options: options,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    );
    return response;
  }

  ///
  Future<Response<T>> delete<T>(
    String uri, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    dynamic key,
  }) async {
    Response<T> response = await request(
      HttpMethod.delete,
      uri,
      data: data,
      queryParameters: queryParameters,
      key: key,
      options: options,
    );
    return response;
  }

  ///
  ///
  Future<Response<T>> patch<T>(
    String uri, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    dynamic key,
    KKProgressCallback? onSendProgress,
    KKProgressCallback? onReceiveProgress,
  }) async {
    Response<T> response = await request(
      HttpMethod.patch,
      uri,
      data: data,
      queryParameters: queryParameters,
      key: key,
      options: options,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    );

    return response;
  }

  /// head 请求
  ///
  Future<Response<T>> head<T>(
    String uri, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    dynamic key,
  }) async {
    Response<T> response = await request(
      HttpMethod.head,
      uri,
      data: data,
      queryParameters: queryParameters,
      key: key,
      options: options,
    );

    return response;
  }

  /// http请求
  ///
  /// [method] 请求方法 HttpMethod.POST
  /// [path] 请求地址
  /// [data] 请求参数
  /// [key] 请求 key,用于记录请求，以便取消请求,如需要取消,请传key值
  /// [queryParameters] 查询参数
  /// [options] 请求 options
  ///
  Future<Response<T>> request<T>(
    HttpMethod method,
    String path, {
    dynamic data,
    dynamic key,
    Map<String, dynamic>? queryParameters,
    Options? options,
    KKProgressCallback? onSendProgress,
    KKProgressCallback? onReceiveProgress,
  }) {
    options ??= Options();
    options.method = method.value();
    CancelToken? token;

    if (key != null) {
      token = _addRequest(key);
    }
    return _dio.request<T>(
      path,
      data: data,
      queryParameters: queryParameters,
      options: options,
      cancelToken: token,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    )..whenComplete(() => cancelRequest(key));
  }

  String _createInnerKey(dynamic key) {
    if (key == null) {
      return "";
    }
    return "$_supmeaCancleKey${key.toString()}_supmea";
  }

  /// 根据key 生成对应的CanclToken
  ///
  /// [key]
  ///
  CancelToken _addRequest(dynamic key) {
    String k = _createInnerKey(key);
    CancelToken token = CancelToken();
    _requests[k] = token;
    return token;
  }

  /// 根据key 取消对应的请求
  ///  @return true 取消成功， false 取消失败
  bool cancelRequest(dynamic key, {bool isFinished = true}) {
    String k = _createInnerKey(key);
    if (k.isEmpty) {
      return false;
    }
    bool con = _requests.keys.toList().contains(k);
    if (con) {
      _requests[k]?.cancel();
      _requests.remove(k);
    }
    if (kDebugMode) {
      if (isFinished) {
        debugPrint("请求完成,不存储请求");
      } else {
        debugPrint("手动取消请求");
      }
    }
    return con;
  }

  /// 取消所有正在进行的请求
  void clear() {
    _requests.values.map((e) => e.cancel());
    _requests.clear();
  }
}
